package com.jhh.pay.center.api;

import com.google.common.base.Strings;
import com.jhh.pay.center.actor.ActorUtil;
import com.jhh.pay.center.actor.DeferredCompleteFunctional;
import com.jhh.pay.center.api.data.DeductRequest;
import com.jhh.pay.center.api.data.PayRequest;
import com.jhh.pay.center.api.data.Result;
import com.jhh.pay.center.model.App;
import com.jhh.pay.center.model.Order;
import com.jhh.pay.center.model.TradeState;
import com.jhh.pay.center.search.PagedList;
import com.jhh.pay.center.search.Searcher;
import com.jhh.pay.center.search.mapping.OrderMapping;
import com.jhh.pay.center.search.query.OrderQuery;
import com.jhh.pay.center.service.AppService;
import com.jhh.pay.center.service.ExistChecker;
import com.jhh.pay.center.service.cloud.message.TradeResult;
import com.jhh.pay.center.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;

import javax.servlet.ServletRequest;
import java.math.BigDecimal;


/**
 * @author tangxd
 * @Description: TODO
 * @date 2017/12/1
 */
@RestController
@RequestMapping("jhhpay/trade")
public class TradeController extends AbstractController {

    @Autowired
    private AppService appService;

    @Autowired
    private ExistChecker existChecker;

    @RequestMapping(value = "/1.0/pay", method = RequestMethod.POST)
    DeferredResult<Result> pay(
            @RequestBody PayRequest data,
            ServletRequest req
    ) {
        DeferredResult<Result> result = new DeferredResult<>();
        if (data.getAppId() <= 0) {
            result.setResult(new Result(TradeState.ERROR, null, "SYS:VLD1001", "appId非法"));
            return result;
        }
        if (data.getBankInfo() == null) {
            result.setResult(new Result(TradeState.ERROR, null, "SYS:VLD1001", "银行信息为填写"));
            return result;
        }
        if (Strings.isNullOrEmpty(data.getBankInfo().getBankCard())) {
            result.setResult(new Result(TradeState.ERROR, null, "SYS:VLD1002", "银行卡号未填写"));
            return result;
        }
        if (Strings.isNullOrEmpty(data.getBankInfo().getPersonalName())) {
            result.setResult(new Result(TradeState.ERROR, null, "SYS:VLD1003", "姓名必须填写"));
            return result;
        }
        if (Strings.isNullOrEmpty(data.getOrderNo())) {
            result.setResult(new Result(TradeState.ERROR, null, "SYS:VLD1004", "订单号不能为空"));
            return result;
        }
        if (data.getMoney() == null || data.getMoney().compareTo(BigDecimal.ZERO) <= 0) {
            result.setResult(new Result(TradeState.ERROR, null, "SYS:VLD1005", "金额错误"));
            return result;
        }
        if (Strings.isNullOrEmpty(data.getNotifyUrl())) {
            result.setResult(new Result(TradeState.ERROR, null, "SYS:VLD1006", "通知地址未填写"));
            return result;
        }
        if (Integer.valueOf(data.getOrderTime()).toString().length() != SECOND_INT_LENGTH) {
            result.setResult(new Result(TradeState.ERROR, null, "SYS:VLD1007", "时间戳错误"));
            return result;
        }
        if (Strings.isNullOrEmpty(data.getSign())) {
            result.setResult(new Result(TradeState.ERROR, null, "SYS:VLD1008", "验证码未填写"));
            return result;
        }

        if (existChecker.exist("PAY-ORDERS-" + data.getAppId(), data.getOrderNo())) {
            result.setResult(new Result(TradeState.ERROR, null, "SYS:VLD1010", "订单号已存在"));
            return result;
        }

        App app = appService.get(data.getAppId());
        if (null == app) {
            result.setResult(new Result(TradeState.ERROR, null, "SYS:VLD1009", "appId不存在"));
            return result;
        }
//        String sign = Md5.encode(String.format("%d%s%d%s", data.getAppId(), data.getOrderNo(), data.getOrderTime(), app.getId()));
//        if (!sign.equals(data.getSign())) {
//            result.setResult(new Result(TradeState.ERROR, "SYS:VLD1010", "sign验证失败"));
//            return result;
//        }

        result = ActorUtil.deferred(
                "PayActor",
                "pay-actor-" + StringUtils.random(10),
                data,
                config.getActorProcessTimeout(),
                (DeferredCompleteFunctional<TradeResult, Result>) (failure, response, r) -> {
                    if (response != null) {
                        r.setResult(new Result(getState(response.getState()), response.getSid(), response.getCode(), response.getMsg()));
                    } else {
                        r.setErrorResult(new Result(TradeState.ERROR, null, "SYS:TIMEOUT", "处理超时"));
                    }
                });
        return result;
    }

    @RequestMapping(value = "/1.0/deduct", method = RequestMethod.POST)
    DeferredResult<Result> deduct(
            @RequestBody DeductRequest data,
            ServletRequest req
    ) {
        DeferredResult<Result> result = new DeferredResult<>();
        if (data.getAppId() <= 0) {
            result.setResult(new Result(TradeState.ERROR, null, "SYS:VLD1101", "appId非法"));
            return result;
        }
        if (data.getBankInfo() == null) {
            result.setResult(new Result(TradeState.ERROR, null, "SYS:VLD1101", "银行信息为填写"));
            return result;
        }
        if (Strings.isNullOrEmpty(data.getBankInfo().getBankCard())) {
            result.setResult(new Result(TradeState.ERROR, null, "SYS:VLD1102", "银行卡号未填写"));
            return result;
        }
        if (Strings.isNullOrEmpty(data.getBankInfo().getPersonalName())) {
            result.setResult(new Result(TradeState.ERROR, null, "SYS:VLD1103", "姓名必须填写"));
            return result;
        }
        if (Strings.isNullOrEmpty(data.getOrderNo())) {
            result.setResult(new Result(TradeState.ERROR, null, "SYS:VLD1104", "订单号不能为空"));
            return result;
        }
        if (data.getMoney() == null || data.getMoney().compareTo(BigDecimal.ZERO) <= 0) {
            result.setResult(new Result(TradeState.ERROR, null, "SYS:VLD1105", "金额错误"));
            return result;
        }
        if (Strings.isNullOrEmpty(data.getNotifyUrl())) {
            result.setResult(new Result(TradeState.ERROR, null, "SYS:VLD1106", "通知地址未填写"));
            return result;
        }
        if (Integer.valueOf(data.getOrderTime()).toString().length() != SECOND_INT_LENGTH) {
            result.setResult(new Result(TradeState.ERROR, null, "SYS:VLD1107", "时间戳错误"));
            return result;
        }
        if (Strings.isNullOrEmpty(data.getSign())) {
            result.setResult(new Result(TradeState.ERROR, null, "SYS:VLD1108", "验证码未填写"));
            return result;
        }

        App app = appService.get(data.getAppId());
        if (null == app) {
            result.setResult(new Result(TradeState.ERROR, null, "SYS:VLD1109", "appId不存在"));
            return result;
        }

        if (existChecker.exist("DEDUCT-ORDERS-" + data.getAppId(), data.getOrderNo())) {
            result.setResult(new Result(TradeState.ERROR, null, "SYS:VLD1110", "订单号已存在"));
            return result;
        }

//        String sign = Md5.encode(String.format("%d%s%d%s", data.getAppId(), data.getOrderNo(), data.getOrderTime(), app.getId()));
//        if (!sign.equals(data.getSign())) {
//            result.setResult(new Result(TradeState.ERROR, "SYS:VLD1110", "sign验证失败"));
//            return result;
//        }
        result = ActorUtil.deferred(
                "DeductActor",
                "deduct-actor-" + StringUtils.random(10),
                data,
                config.getActorProcessTimeout(),
                (DeferredCompleteFunctional<TradeResult, Result>) (failure, response, r) -> {
                    if (response != null) {
                        r.setResult(new Result(getState(response.getState()), response.getSid(), response.getCode(), response.getMsg()));
                    } else {
                        r.setErrorResult(new Result(TradeState.ERROR, null, "SYS:TIMEOUT", "处理超时"));
                    }
                });
        return result;
    }
}
